﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Qiniu.Common;
using Qiniu.Http;
using Qiniu.IO;
using Qiniu.IO.Model;
using Qiniu.Util;

namespace lyAdmin.Common
{
    /// <summary>
    /// 七牛
    /// </summary>
    public class QiniuClient
    {
        private static Mac mac = null;
        private static Auth _Auth;
        private static string _AK;
        private static string _SK;
        private static string _BUCKET;
        private string domain;
        /// <summary>
        /// 构造函数
        /// </summary>
        public QiniuClient()
        {

        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="AK">Access Key</param>
        /// <param name="SK">Secret Key</param>
        /// <param name="BUCKET">BUCKET</param>
        public QiniuClient(string AK,string SK,string BUCKET)
        {
            _AK = AK;
            _SK = SK;
            _BUCKET = BUCKET;
            // 生成(上传)凭证时需要使用此Mac
            // 这个示例单独使用了一个Settings类，其中包含AccessKey和SecretKey
            // 实际应用中，请自行设置您的AccessKey和SecretKey 
            mac = new Mac(AK, SK);
            _Auth = new Auth(mac);
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="data">文件路径二进制</param>
        /// <param name="filename">文件名称，例如：file.png</param>
        /// <param name="BUCKET"></param>
        /// <param name="USE_HTTPS"></param>
        /// <returns></returns>
        public static string UploadData(byte[] data,string filename,string BUCKET="", bool USE_HTTPS=true)
        {
            if (BUCKET == "")
                BUCKET = _BUCKET;
            Qiniu.Common.Config.AutoZone(_AK, _BUCKET, USE_HTTPS); 
            string saveKey = filename; 
            // 上传策略，参见 
            // https://developer.qiniu.com/kodo/manual/put-policy
            PutPolicy putPolicy = new PutPolicy();
            // 如果需要设置为"覆盖"上传(如果云端已有同名文件则覆盖)，请使用 SCOPE = "BUCKET:KEY"
            // putPolicy.Scope = bucket + ":" + saveKey;
            putPolicy.Scope = BUCKET;
            // 上传策略有效期(对应于生成的凭证的有效期)          
            putPolicy.SetExpires(3600);
            // 上传到云端多少天后自动删除该文件，如果不设置（即保持默认默认）则不删除
            //putPolicy.DeleteAfterDays = 1;
            // 生成上传凭证，参见
            // https://developer.qiniu.com/kodo/manual/upload-token            
            string jstr = putPolicy.ToJsonString();
            string token = Auth.CreateUploadToken(mac, jstr);
            UploadManager um = new UploadManager();
            HttpResult result = um.UploadData(data, saveKey, token);
            Console.WriteLine(result);

            return result.Text;
        }


        /// <summary>
        /// 上传服务器文件
        /// </summary>
        /// <param name="localFile">上传文件目录,例如：D:\\QFL\\1.png</param>
        /// <param name="filename">文件名称，例如：1.png</param>
        /// <param name="BUCKET"></param>
        /// <param name="USE_HTTPS"></param>
        public string UploadFile(string localFile, string filename, string BUCKET = "", bool USE_HTTPS = true)
        {
            if (BUCKET == "")
                BUCKET = _BUCKET;
            Qiniu.Common.Config.AutoZone(_AK, _BUCKET, USE_HTTPS);
            // 生成(上传)凭证时需要使用此Mac
            // 这个示例单独使用了一个Settings类，其中包含AccessKey和SecretKey
            // 实际应用中，请自行设置您的AccessKey和SecretKey
            Mac mac = new Mac(_AK, _SK); 
            string saveKey = filename;  
            // 上传策略，参见 
            // https://developer.qiniu.com/kodo/manual/put-policy
            PutPolicy putPolicy = new PutPolicy();
            // 如果需要设置为"覆盖"上传(如果云端已有同名文件则覆盖)，请使用 SCOPE = "BUCKET:KEY"
            // putPolicy.Scope = bucket + ":" + saveKey;
            putPolicy.Scope = BUCKET;
            // 上传策略有效期(对应于生成的凭证的有效期)          
            putPolicy.SetExpires(3600);
            // 上传到云端多少天后自动删除该文件，如果不设置（即保持默认默认）则不删除
            //putPolicy.DeleteAfterDays = 1;
            // 生成上传凭证，参见
            // https://developer.qiniu.com/kodo/manual/upload-token            
            string jstr = putPolicy.ToJsonString();
            string token = Auth.CreateUploadToken(mac, jstr);
            UploadManager um = new UploadManager();
            HttpResult result = um.UploadFile(localFile, saveKey, token);
            Console.WriteLine(result); 

            return result.Text;
        }
        /// <summary>
        /// 断点续上传
        /// </summary>
        /// <param name="localFile">服务器文件目录,D:\\QFL\\resume.jpg</param>
        /// <param name="filename">文件名,resume.jpg</param>
        /// <param name="BUCKET"></param>
        /// <param name="USE_HTTPS"></param>
        /// <returns></returns>
        public string UploadBigFile(string localFile, string filename, string BUCKET = "", bool USE_HTTPS = true)
        {
            if (BUCKET == "")
                BUCKET = _BUCKET;
            Qiniu.Common.Config.AutoZone(_AK, _BUCKET, USE_HTTPS);
            // 这个示例单独使用了一个Settings类，其中包含AccessKey和SecretKey
            // 实际应用中，请自行设置您的AccessKey和SecretKey
            Mac mac = new Mac(_AK, _SK); 
            string saveKey = filename; 
            // 断点记录文件，可以不用设置，让SDK自动生成，如果出现续上传的情况，SDK会尝试从该文件载入断点记录
            // 对于不同的上传任务，请使用不同的recordFile
            string recordFile = filename;
            PutPolicy putPolicy = new PutPolicy();
            putPolicy.Scope = BUCKET;
            putPolicy.SetExpires(3600);
            string token = Auth.CreateUploadToken(mac, putPolicy.ToJsonString());
            // 包含两个参数，并且都有默认值
            // 参数1(bool): uploadFromCDN是否从CDN加速上传，默认否
            // 参数2(enum): chunkUnit上传分片大小，可选值128KB,256KB,512KB,1024KB,2048KB,4096KB
            ResumableUploader ru = new ResumableUploader(false, ChunkUnit.U1024K);
            // ResumableUploader.UploadFile有多种形式，您可以根据需要来选择
            //
            // 最简模式，使用默认recordFile和默认uploadProgressHandler
            // UploadFile(localFile,saveKey,token)
            // 
            // 基本模式，使用默认uploadProgressHandler
            // UploadFile(localFile,saveKey,token,recordFile)
            //
            // 一般模式，使用自定义进度处理(可以监视上传进度)
            // UploadFile(localFile,saveKey,token,recordFile,uploadProgressHandler)
            //
            // 高级模式，包含上传控制(可控制暂停/继续 或者强制终止)
            // UploadFile(localFile,saveKey,token,recordFile,uploadProgressHandler,uploadController)
            // 
            // 支持自定义参数
            //var extra = new System.Collections.Generic.Dictionary<string, string>();
            //extra.Add("FileType", "UploadFromLocal");
            //extra.Add("YourKey", "YourValue");
            //uploadFile(...,extra,...)
            //最大尝试次数(有效值1~20)，在上传过程中(如mkblk或者bput操作)如果发生错误，它将自动重试，如果没有错误则无需重试
            int maxTry = 10;
            // 使用默认进度处理，使用自定义上传控制            
            UploadProgressHandler upph = new UploadProgressHandler(ResumableUploader.DefaultUploadProgressHandler);
            UploadController upctl = new UploadController(uploadControl);
            HttpResult result = ru.UploadFile(localFile, saveKey, token, recordFile, maxTry, upph, upctl);
            Console.WriteLine(result);
            return result.Text;
        }
        // 内部变量，仅作演示
        private static bool paused = false;
        /// <summary>
        /// AccessKey
        /// </summary>
        public string AccessKey { get => _AK; set => _AK = value; }
        /// <summary>
        /// SecretKey
        /// </summary>
        public string SecretKey { get => _SK; set => _SK = value; }
        /// <summary>
        /// Bucket
        /// </summary>
        public string Bucket { get => _BUCKET; set => _BUCKET = value; }
        /// <summary>
        /// 七牛绑定域名
        /// </summary>
        public string Domain { get => domain; set => domain = value; }

        /// <summary>
        /// 上传控制
        /// </summary>
        /// <returns></returns>
        private static UPTS uploadControl()
        {
            // 这个函数只是作为一个演示，实际当中请根据需要来设置
            // 这个演示的实际效果是“走走停停”，也就是停一下又继续，如此重复直至上传结束
            paused = !paused;
            if (paused)
            {
                return UPTS.Suspended;
            }
            else
            {
                return UPTS.Activated;
            }
        }
    }
}
